﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace Groove.Winform.Component
{
    public delegate void ScrollBarValueChangedDelegate(int scollbarValue);

    public partial class ScrollBar : Control
    {
        //const int ScrollBarWidth = 10;
        const int MinimumScrollBarHeight = 20;
        const int MouseWheelStep = 20;
        private float _zoomScale = 1;
        private int _scrollBarHeight;
        private int _currentPositon;

        private int _totalHeight;
        public int TotalHeight
        {
            get => _totalHeight;
            set
            {
                if (value < Height) value = Height;
                _totalHeight = value;
                SetVisiableParams();
            }
        }

        private int ScrollHeight
        {
            get
            {
                return TotalHeight <= Height ? 0 : TotalHeight - Height;
            }
        }

        private int CurrentPosition
        {
            get => _currentPositon;
            set
            {
                if (value < 0) value = 0;
                if (value > Height - _scrollBarHeight) value = Height - _scrollBarHeight;
                _currentPositon = value;
                SetValue();
                Invalidate();
            }
        }

        public int Value { get; private set; }

        public event ScrollBarValueChangedDelegate ScrollBarValueChanged;

        public ScrollBar()
        {
            DoubleBuffered = true;
            SetStyle(ControlStyles.DoubleBuffer | ControlStyles.SupportsTransparentBackColor, true);
            InitializeComponent();
            MouseDown += ScrollBarMouseDown;
            MouseUp += ScrollBarMouseUp;
            MouseMove += ScrollBarMouseMove;
            MouseLeave += ScrollBarMouseLeave;
        }

        private void SetVisiableParams()
        {
            if (ScrollHeight <= 0)
            {
                Visible = false;
                _zoomScale = 1;
                _scrollBarHeight = 0;                
                return;
            }
            else
            {
                Visible = true;
                var scrollBarHeight = Height - ScrollHeight;
                if (scrollBarHeight >= MinimumScrollBarHeight)
                {
                    _scrollBarHeight = scrollBarHeight;
                    _zoomScale = 1;
                }
                else
                {
                    _scrollBarHeight = MinimumScrollBarHeight;
                    _zoomScale = ScrollHeight * 1f / (Height - MinimumScrollBarHeight);
                }
            }
            CurrentPosition = 0;
        }

        private void SetValue()
        {
            Value = (int)(CurrentPosition * _zoomScale);
            ScrollBarValueChanged?.Invoke(Value);
        }

        RectangleF _scrollBarRect;
        //bool _isActive;
        //int _mouseDownPosition;

        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);
            var g = pe.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.Clear(BackColor);

            if (_scrollBarHeight == 0 || !Visible) return;
            _scrollBarRect = new RectangleF(0, _currentPositon, Width, _scrollBarHeight);
            var barColor = Color.FromArgb(73, 73, 73);
            var mp = PointToClient(MousePosition);
            var isHover = _scrollBarRect.Contains(mp);
            if (isHover)
                barColor = Color.FromArgb(119, 119, 119);
            //if (_isActive)
            //    barColor = Color.FromArgb(164, 164, 164);
            using (var brush = new SolidBrush(barColor))
            {
                g.FillRectangle(brush, _scrollBarRect);
            }
        }

        private void ScrollBarMouseLeave(object sender, EventArgs e)
        {
            Invalidate();
        }

        private void ScrollBarMouseMove(object sender, MouseEventArgs e)
        {
            // TODO: 暂时仅支持鼠标滚轮拖动
            //if (!_isActive) return;
            //var delta = e.Y - _mouseDownPosition;            
            //CurrentPosition = CurrentPosition + delta;
        }

        private void ScrollBarMouseUp(object sender, MouseEventArgs e)
        {
            // TODO: 暂时仅支持鼠标滚轮拖动
            //if (e.Button != MouseButtons.Left || !_isActive) return;
            //_isActive = false;
            //Invalidate();
        }

        private void ScrollBarMouseDown(object sender, MouseEventArgs e)
        {
            // TODO: 暂时仅支持鼠标滚轮拖动
            //if (e.Button != MouseButtons.Left) return;
            //if(_scrollBarRect.Contains(e.Location))
            //{
            //    _isActive = true;
            //    _mouseDownPosition = e.Y;
            //    Invalidate();
            //}
        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            base.OnMouseClick(e);
            // TODO: 暂时仅支持鼠标滚轮拖动
            //if (_scrollBarRect.Contains(e.Location)) return;
            //CurrentPosition = e.Y - _scrollBarHeight / 2;
        }

        protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);
            OnParentMouseWheel(e.Delta);
        }

        public void OnParentMouseWheel(int delta)
        {
            var range = delta > 0 ? -1* MouseWheelStep : MouseWheelStep;
            CurrentPosition += range;
        }
    }
}
